<?php
/**
 * @author ciogao@gmail.com
 * Date: 15-10-16 上午11:22
 *
 *
 * demo:
 * 翻译某目录下所有po文件
 * php TransPo.php -p ./po -t en
 *
 *
 *
 */
class TransPo
{
    private $translateDir = 'translation';
    private $isOutPutProcess = 1;

    private $aLanguage = array('en', 'cht'); //英文 繁体中文
    private $sLanguage = NULL;

    private $extensionsAll = array('po');

    private $aDomainFileter = array();
    private $aTransCache = array();

    private $sPoPath = NULL;

    private $count = 0;

    public function __construct($argv)
    {
        if ('cli' != php_sapi_name()) {
            error_log("ERROR: This program is for command line mode only.");
            exit(1);
        }

        $opt = getopt('d:t:p:');
        if ($opt) {
            if (array_key_exists('d', $opt)) {
                $tmp                  = $opt['d'];
                $this->aDomainFileter = explode(',', $tmp);
            }

            if (array_key_exists('t', $opt) && in_array($opt['t'], $this->aLanguage)) {
                $this->sLanguage = $opt['t'];
            }

            if (array_key_exists('p', $opt)) {
                $this->sPoPath = $opt['p'];
            }
        }
    }

    /**
     * @param $dir
     */
    private function do_dir($dir)
    {
        $d = dir($dir);

        while (FALSE !== ($entry = $d->read())) {
            if ($entry == '.' || $entry == '..') {
                continue;
            }

            $entry = $dir . '/' . $entry;

            if (is_dir($entry)) { // if a directory, go through it
                $this->do_dir($entry);
            } else { // if file, parse only if extension is matched
                $pi = pathinfo($entry);
                if (isset($pi['extension']) && in_array($pi['extension'], $this->extensionsAll)) {
                    $this->do_file($entry);
                }
            }
        }

        $d->close();
    }

    /**
     * @param $file
     *
     * @todo
     *
     * 正则取得 msgid 与 msgstr, 如果msgstr不为空, 则不再翻译； 如果为空, 则调用翻译接口, 并替换原msgstr
     *
     */
    private function do_file($file)
    {
        $this->translationFile($file);
    }

    private function translationFile($fileName){

        if(!file_exists($fileName)){
            echo "{$fileName}不存在，请检查!\n";
            exit;
        }

        $file = fopen($fileName, "r") or exit("Unable to open {$fileName}!");


        //生成新的翻译文件
        $suffix = pathinfo($fileName, PATHINFO_EXTENSION);
        $newFileName = $this->translateDir.'/'.basename($fileName,$suffix).$suffix;
        $myfile = fopen($newFileName, "w") or die("Unable to open {$newFileName}!");

        fwrite($myfile,"msgid \"\"\n");
        fwrite($myfile,"msgstr \"\"\n");

        $msgid = "";
        $msgstr = "";

        $msgid_pattern = "/^msgid\s\"(.*?)\"/";
        $msgstr_pattern = "/^msgstr\s\"(.*?)\"/";

        $msg_arr = array(
            'msgid' => '',
            'msgstr' => ''
        );

        while(!feof($file))
        {
            $str = fgets($file);

            if($is_msgid = preg_match($msgid_pattern,$str,$match_msgid)){
                $msg_arr['msgid'] = $match_msgid[1];
                if(!$msg_arr['msgid']){
                    continue;
                }
            }

            if($is_msgstr = preg_match($msgstr_pattern,$str,$match_msgstr)){
                if($msg_arr['msgid'] !="" && $match_msgstr[1] == ""){
                    sleep(0.5);
                    $msgstr = $this->transWithBaidu($msg_arr['msgid'],$this->sLanguage);//翻译$msg_arr['msg_id']
                    if($this->isOutPutProcess == 1){
                        $this->count++;
                        echo "{$fileName}=>{$this->count}=>{$msg_arr['msgid']} => {$msgstr}\n";
                    }else{
                        echo "{$fileName}=>没有被翻译的id=>{$msg_arr['msgid']}";
                    }
                }else{
                    $msgstr = $match_msgstr[1];
                }

                $msg_arr['msgstr'] = $msgstr;
            }

            if($msg_arr['msgid'] != "" && $msg_arr['msgstr'] != ""){
                $msgid_str = 'msgid "'.$msg_arr['msgid']."\"\n";
                $msgstr_str = 'msgstr "'.$msg_arr['msgstr']."\"\n";
                fwrite($myfile, $msgid_str);
                fwrite($myfile, $msgstr_str);

                $msg_arr['msgid'] = "";
                $msg_arr['msgstr'] = "";
            }

            if(!$is_msgid && !$is_msgstr){
                fwrite($myfile,$str);
            }

        }

        fclose($file);
        fclose($myfile);
        system("dos2unix {$newFileName}",$a);
    }

    /**
     * @param        $str
     * @param        $to
     * @param string $from
     *
     * @return bool
     */
    private function transWithBaidu($str, $to, $from = 'zh')
    {
        $sKey = md5($str . $to . $from);
        if (array_key_exists($sKey, $this->aTransCache)) {
            return $this->aTransCache[$sKey];
        }


        $data = array('from' => $from, 'to' => $to, 'query' => $str, 'transtype' => 'trans', 'simple_means_flag' => 3);
        $url  = "http://fanyi.baidu.com/v2transapi";
        $ch   = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        $output = json_decode(curl_exec($ch), TRUE);
        curl_close($ch);

        if (is_array($output) && count($output) > 1 && array_key_exists('trans_result', $output) && array_key_exists('data', $output['trans_result'])) {
            if (isset($output['trans_result']['data'][0]['dst'])) {
                $result                   = $output['trans_result']['data'][0]['dst'];
                $this->aTransCache[$sKey] = $result;

                return $result;
            }
        }

        return FALSE;
    }

    private function mkTranslationDir(){

        if(!is_dir($this->translateDir)){
            mkdir($this->translateDir,0777,true);
        }else{
            //清空目录下的所有文件
            $dh=opendir($this->translateDir);
            while ($file=readdir($dh)) {
                if($file!="." && $file!="..") {
                    $fullpath=$this->translateDir."/".$file;
                    if(!is_dir($fullpath)) {
                        unlink($fullpath);
                    }
                }
            }
        }

    }
    public function run()
    {
        $this->mkTranslationDir();

        $this->do_dir($this->sPoPath);
    }

}

$oTrans = new TransPo($argv);
$oTrans->run();